home *** CD-ROM | disk | FTP | other *** search
/ MacFormat España 27 / MacFormat n. 27 (Spain) / Mac Format 26.bin / Shareware / Programación / Word Services XCMD 1.0d3 / Sources / old DoBatchEvt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-18  |  9.7 KB  |  400 lines

  1. // DoBatchEvt.c
  2. // Copyright © Michael D. Crawford.  All Rights Reserved.
  3. // mail bug reports and enhancement suggestions to crawford@scruznet.com
  4. // get updates from:
  5. // http://www.scruznet.com/~crawford/WordServices/wdsvindex.html
  6. // DoBatchEvt creatorCode [ fieldNumber ] [ cardNumber ]
  7. // Optional params default to 1.
  8. //
  9. //    Version history
  10. //  1.0d2    MDC        Added params for card and field number
  11. //    1.0d1    MDC        First release
  12.  
  13. #include <HyperXCMD.h>
  14. #include <Aliases.h>
  15. #include <Processes.h>
  16. #include <AppleEvents.h>
  17. #include <AEObjects.h>
  18. #include <AEPackObject.h>
  19. #include <AERegistry.h>
  20.  
  21. #include "TestBedPrefix.h"
  22. #include "FindProcess.h"
  23. #include "Gripe.h"
  24. #include "WordServices.h"
  25. #include "FindSpeller.h"
  26.  
  27. OSErr DoBatchCheck( AEAddressDesc *spellerAddrPtr, long fieldNumber, long cardNumber );
  28. OSErr CreateTextSpecifier( long windowNumber, long textNumber, AEDesc *specPtr );
  29. OSErr BuildWindowSpecifier( AEDesc *specPtr, long whichWindow );
  30. OSErr CreateFieldSpecifier( long cardNumber, long fieldNumber, AEDesc *specPtr );
  31. OSErr BuildCardSpecifier( AEDesc *specPtr, long whichWindow );
  32. void HandleStrToPStr( Handle h, StringPtr str );
  33.  
  34. #define kBatchTimeout    600
  35.  
  36. #ifdef XCMD_TESTBED
  37. void CallXCmd( XCmdPtr pBPtr )
  38. #else
  39. pascal void main( XCmdPtr pBPtr )
  40. #endif
  41. {
  42.     OSType                signature;
  43.     ProcessSerialNumber psn;
  44.     ProcessInfoRec        pInfo;
  45.     OSErr                err;
  46.     AEAddressDesc        spellerAddr;
  47.     long                cardNumber;
  48.     long                fieldNumber;
  49.     Str255                strBuf;
  50.     Boolean                foundIt;
  51.  
  52.     if ( pBPtr->paramCount < 1 || pBPtr->paramCount > 3 ){
  53.         pBPtr->returnValue = NewHandle( 9 );
  54.         if ( pBPtr->returnValue )
  55.             BlockMoveData( "paramErr", *( pBPtr->returnValue ), 9 );
  56.     }
  57.     
  58.     BlockMove( *( pBPtr->params[ 0 ] ), &signature, 4 );
  59.     
  60.     // Defaults
  61.     
  62.     cardNumber = 1;
  63.     fieldNumber = 1;
  64.  
  65.     if ( pBPtr->paramCount > 1 ){
  66.         HandleStrToPStr( pBPtr->params[ 1 ], strBuf );
  67.         StringToNum( strBuf, &fieldNumber );        
  68.     }
  69.     
  70.     if ( pBPtr->paramCount > 2 ){
  71.         HandleStrToPStr( pBPtr->params[ 2 ], strBuf );
  72.         StringToNum( strBuf, &cardNumber );        
  73.     
  74.     }
  75. Debugger();
  76.     err = FindSpeller( signature, &foundIt );
  77.     if ( err || !foundIt )
  78.         return;
  79.  
  80.     err = AECreateDesc( typeApplSignature,
  81.                         (Ptr)&signature,
  82.                         sizeof( signature ),
  83.                         &spellerAddr );
  84.     if ( err ){
  85.         Gripe( "\pAECreateDesc failed" );
  86.         return;
  87.     }
  88.  
  89.     err = DoBatchCheck( &spellerAddr, fieldNumber, cardNumber );
  90.     if ( err ){
  91.         DebugStr( "\pDoBatchCheck failed" );
  92.         return;
  93.     }
  94.  
  95.     return;
  96. }
  97.  
  98. OSErr DoBatchCheck( AEAddressDesc *spellerAddrPtr, long fieldNumber, long cardNumber )
  99. {
  100.     OSErr            err;
  101. //    AEDesc            textSpecifier;
  102.     AEDesc            fieldSpecifier;
  103.     AppleEvent        btchEvent;
  104.     AppleEvent        replyEvent;
  105. //    WWJrPrefsHdl    prefHdl;
  106.     AEDescList        textSpecList;            /* 1.0d7 */
  107.     long            index;                    /* 1.0d7 */
  108.  
  109.     /* We make an object specifier that refers to _our_own_ window
  110.      */
  111.  
  112. //    err = CreateTextSpecifier( 1L, 1L, &textSpecifier );
  113.     err = CreateFieldSpecifier( cardNumber, fieldNumber, &fieldSpecifier );
  114.     
  115.     if ( err ){
  116.         Gripe( "\pCreateFieldSpecifier failed" );
  117.         return err;
  118.     }
  119.  
  120. //    prefHdl = GetPrefHandle();
  121. //    if ( !prefHdl ){
  122. //        Gripe( "\pCannot get preferences handle" );
  123. //        return resNotFound;
  124. //    }
  125. //    
  126. //    if ( (*prefHdl)->checkSel ){
  127. //        /* Make a formRange descriptor that gives the selection range */
  128. //
  129. //        Gripe( "\pSelection-only checking is not yet implemented" );
  130. //        return noErr;
  131. //    }
  132.  
  133.     /* Create the event to send to the speller */
  134.     
  135.     err = AECreateAppleEvent( kWordServicesClass,
  136.                                 kWSBatchCheckMe,
  137.                                 spellerAddrPtr,
  138.                                 kAutoGenerateReturnID,
  139.                                 kAnyTransactionID,
  140.                                 &btchEvent );
  141.     
  142.     if ( err ){
  143.         Gripe( "\pcreate btch event failed" );
  144.         return err;
  145.     }
  146.     err = AEDisposeDesc( spellerAddrPtr );
  147.     if ( err ){
  148.         Gripe( "\pAEDisposeDesc failed" );
  149.         return err;
  150.     }
  151.  
  152.  
  153.     /* 1.0d7 This is the new way to do it - use a list of object specifiers (even if
  154.      * only one of them
  155.      */
  156.     
  157.     err = AECreateList( (Ptr)NULL, (Size)0, false, &textSpecList );
  158.     if ( err ){
  159.         Gripe( "\pAECreateList failed" );
  160.         return err;
  161.     }
  162.     
  163.     /* Put our specifier into it.  If we had multiple text blocks to check, we would
  164.      * put specifiers for each into it in turn.
  165.      * Note that we use AEPutDesc, not AEPutParamDesc, to put items into an indexed
  166.      * list.
  167.      */
  168.  
  169. #define N_TEXT_SPECS    1L /*3L    */    /* Define this to be 1 for normal checking */
  170.  
  171.     for ( index = 1L; index <= N_TEXT_SPECS; index++ ){
  172.         err = AEPutDesc( &textSpecList,
  173.                             index,
  174.                             &fieldSpecifier );
  175.         if ( err ){
  176.             Gripe( "\pAEPutDesc failed to put text specifier into textSpecList" );
  177.             return err;
  178.         }
  179.     }
  180.  
  181.     err = AEDisposeDesc( &fieldSpecifier );
  182.     if ( err ){
  183.         Gripe( "\pAEDisposeDesc failed" );
  184.         return err;
  185.     }
  186.  
  187.     /* Insert the list of object specifiers as the direct object of the batch event */
  188.  
  189.     err = AEPutParamDesc( &btchEvent,
  190.                             keyDirectObject,
  191.                             &textSpecList );
  192.     if ( err ){
  193.         Gripe( "\pAEPutParamDesc failed to put direct object on batch event" );
  194.         return err;
  195.     }
  196.     
  197.     /* 1.0.3 MDC fixed a bug in which we disposed of textSpecifier a second
  198.      * time, instead of properly disposing of textSpecList
  199.      */
  200.  
  201.     err = AEDisposeDesc( &textSpecList );
  202.     if ( err ){
  203.         Gripe( "\pAEDisposeDesc failed" );
  204.         return err;
  205.     }
  206.  
  207.     /* Send the event.  We await the reply, so that if there is a failure of some
  208.      * sort in the initial connection, we can alert the user right away.  The timeout
  209.      * value to use here should be as long as one would care to have a user wait for
  210.      * the completion of a menu command.  Since we expect that the speller is on a local
  211.      * machine in this case, and should be able to respond immediately, we just give
  212.      * a few seconds for the timeout.
  213.      *
  214.      * We should assign an idle proc to spin the cursor.  Even better would be a progress
  215.      * dialog that says "Contacting speller" or some such, with an animated display that
  216.      * shows the time elapsed relative to the total timeout, so the user will know how
  217.      * long she may have to wait
  218.      */
  219.     
  220.     err = AESend( &btchEvent,
  221.                     &replyEvent,
  222.                     kAEWaitReply + kAECanInteract + kAECanSwitchLayer,
  223.                     kAENormalPriority,
  224.                     kBatchTimeout,
  225.                     (AEIdleUPP)NULL,
  226.                     (AEFilterUPP)NULL );
  227.     
  228.     if ( err ){
  229.         Gripe( "\psend batch event failed" );
  230.         return err;
  231.     }
  232.     err = AEDisposeDesc( &btchEvent );
  233.     if ( err ){
  234.         Gripe( "\pAEDisposeDesc failed" );
  235.         return err;
  236.     }
  237.     
  238.     /* MDC 1.1.1 fix a memory leak */
  239.  
  240.     err = AEDisposeDesc( &replyEvent );
  241.     if ( err ){
  242.         Gripe( "\pAEDisposeDesc failed" );
  243.         return err;
  244.     }
  245.     
  246.     /* Now the event has been sent.  There is nothing more that we have to actually do
  247.      * on our own initiative to accomplish the spelling; we just sit back and respond
  248.      * to events.  In particular, we don't remember that spelling is taking place - once
  249.      * the spelling is done, we will just start seeing events from the user (mouse and
  250.      * key clicks and so on
  251.      */
  252.     
  253.     return noErr;
  254. }
  255.  
  256. /*
  257.  * Descriptor packing routines
  258.  */
  259.  
  260. /* Create a formAbsolutePosition window descriptor */
  261.  
  262. OSErr BuildCardSpecifier( AEDesc *specPtr, long whichWindow )
  263. {
  264.     AEDesc    nullDesc;
  265.     AEDesc    nullSpec;
  266.     AEDesc    whichDesc;
  267.     OSErr    err;
  268.     
  269.     /* Create the descriptor for the container (the application, or null) */
  270.  
  271.     err = AECreateDesc( typeNull, (Ptr)NULL, (Size)0, &nullDesc );
  272.     if ( err )
  273.         return err;
  274.     
  275.     /* Create the key data, which gives the window number */
  276.     
  277.     err = CreateOffsetDescriptor( whichWindow, &whichDesc );
  278.     if ( err )
  279.         return err;
  280.  
  281.     /* Create the Object Specifier for the window */
  282.     
  283.     err = CreateObjSpecifier( 'cCRD',
  284.                                 &nullDesc,
  285.                                 formAbsolutePosition,
  286.                                 &whichDesc,
  287.                                 true,                    /* Dispose of input descriptors */
  288.                                 specPtr );                /* specPtr is the value we return */
  289.     return err;
  290. }
  291.  
  292. #ifdef NEVER
  293. OSErr CreateTextSpecifier( long windowNumber, long textNumber, AEDesc *specPtr )
  294. {
  295.     AEDesc    docSpecifier;
  296.     AEDesc    textDescriptor;
  297.     OSErr    err;
  298.  
  299.     /* Create an object specifier for a particular text field within a particular
  300.      * window. In each case use formAbsolutePosition.
  301.      */
  302.  
  303.     err = BuildWindowSpecifier( &docSpecifier, windowNumber );
  304.     if ( err ){
  305.         Gripe( "\pBuildWindowDescriptor failed" );
  306.         return err;
  307.     }
  308.     
  309.     err = CreateOffsetDescriptor( textNumber, &textDescriptor );
  310.     if ( err ){
  311.         Gripe( "\pCreateOffsetDescriptor failed" );
  312.         return err;
  313.     }
  314.     
  315.     err = CreateObjSpecifier( cText,
  316.                                 &docSpecifier,
  317.                                 formAbsolutePosition,
  318.                                 &textDescriptor,
  319.                                 true,                        /* Dispose input descriptors */
  320.                                 specPtr );
  321.     if ( err ){
  322.         Gripe( "\pCreateObjSpecifer failed" );
  323.         return err;
  324.     }
  325.  
  326.     return noErr;
  327. }
  328. #endif
  329.  
  330. OSErr CreateFieldSpecifier( long cardNumber, long fieldNumber, AEDesc *specPtr )
  331. {
  332.     AEDesc    docSpecifier;
  333.     AEDesc    fieldDescriptor;
  334.     AEDesc    nullDesc;
  335.     OSErr    err;
  336.  
  337.     /* Create an object specifier for a particular text field within a particular
  338.      * window. In each case use formAbsolutePosition.
  339.      */
  340.  
  341.     err = BuildCardSpecifier( &docSpecifier, cardNumber );
  342.     if ( err ){
  343.         Gripe( "\pBuildWindowDescriptor failed" );
  344.         return err;
  345.     }
  346.  
  347.     
  348. //    err = AECreateDesc( typeNull, (Ptr)NULL, (Size)0, &nullDesc );
  349. //    if ( err )
  350. //        return err;
  351.  
  352.     err = CreateOffsetDescriptor( fieldNumber, &fieldDescriptor );
  353.     if ( err ){
  354.         Gripe( "\pCreateOffsetDescriptor failed" );
  355.         return err;
  356.     }
  357.     
  358.     err = CreateObjSpecifier( 'cCFD',
  359.                                 &docSpecifier,
  360.                                 formAbsolutePosition,
  361.                                 &fieldDescriptor,
  362.                                 true,                        /* Dispose input descriptors */
  363.                                 specPtr );
  364.  
  365. //    err = CreateObjSpecifier( 'cCFD',
  366. //                                &nullDesc,
  367. //                                formAbsolutePosition,
  368. //                                &fieldDescriptor,
  369. //                                true,                        /* Dispose input descriptors */
  370. //                                specPtr );
  371.     if ( err ){
  372.         Gripe( "\pCreateObjSpecifer failed" );
  373.         return err;
  374.     }
  375.  
  376.     return noErr;
  377. }
  378.  
  379. void HandleStrToPStr( Handle h, StringPtr str )
  380. {
  381.     short    size;
  382.     char    *p;
  383.  
  384.     // Convert a handle to a C string into a Pascal string
  385.  
  386.     p = *h;
  387.     size = 0;
  388.  
  389.     while ( *p++ )
  390.         size++;
  391.     
  392.     if ( size > 255 )
  393.         size = 255;
  394.  
  395.     str[ 0 ] = (unsigned char)size;
  396.     
  397.     BlockMove( *h, &str[ 1 ], size );
  398.  
  399.     return;
  400. }